package bj

import scala.swing._
import swing.event._
import java.awt.image._
import javax.imageio.ImageIO._
import java.awt.Graphics
import scala.swing.BorderPanel
import javax.swing.JPanel
import javax.swing.ImageIcon
import javax.swing.table._
import scala.actors.Actor
import Actor._
import scala.actors.remote.RemoteActor.{ alive, register }
import scala.actors.remote.RemoteActor
import scala.actors.remote.Node
import scala.actors.remote.NetKernel
import scala.actors.AbstractActor
import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import java.net._
import bj.hkeeping.PlayerMsg
import bj.hkeeping.SetBank
import bj.hkeeping.ClientBet
import bj.hkeeping.GetPid
import bj.actor.GameServer
import bj.actor.Player
import bj.actor.RemotePlayer
import bj.actor.House
import bj.actor.Dealer
import bj.actor.Go
import bj.util.Logs
import org.apache.log4j.Logger
import org.apache.log4j.Level
import org.apache.log4j.PropertyConfigurator

case class PlayerPid(playerId: Int)
case class SendMsgPlayerName(jbGameServer: AbstractActor, playerName: String)
case class SendMsgSetBank(jbGameServer: AbstractActor, bankRoll: Double, clientPid: Int)
case class SendMsgMakeABet(jbGameServer: AbstractActor, betAmount: Double, clientPid: Int)

class ClientPlayer(clientServiceName: Symbol, clientIpAddress: String, clientPort: Int, 
				   clientName: String, clientBankRoll: Double, clientBet: Double) extends Actor with Logs{
  var Pid = -1
  
  def act {
    // Declare the port I'm listening on
    alive(clientPort)

    // Register me
    register(clientServiceName, self)
    
    loop {
      react {
        case SendMsgPlayerName(jbGameServer: AbstractActor, playerName: String) => 
          jbGameServer ! PlayerMsg(playerName)
        
        case GetPid(playerId) => Pid = playerId; debug("Pid=playerId is: " + Pid)
        
        case SendMsgSetBank(jbGameServer: AbstractActor, bankRoll: Double, clientPid: Int) => 
          jbGameServer ! SetBank(clientPid, bankRoll)
        
        case SendMsgMakeABet(jbGameServer: AbstractActor, betAmount: Double, clientPid: Int) => 
          jbGameServer ! ClientBet(clientPid, betAmount)
      }
    }
  }
  
}

object ClientPlayer {
  RemoteActor.classLoader = getClass().getClassLoader()
 
 /**
  * Remote Client 
  * 
  */
  val hostClientPort        = 14501
  val hostClientServiceName = 'personPlayer
  val hostClientLocalHost   = InetAddress.getLocalHost
  val hostClientIpAddress     = hostClientLocalHost.getHostAddress

  /**
   * Remote Casino Server
   * 
   */
  val CasinoPort           = 14500
  val CasinoServiceName    = 'jackBlack_Casino
  val CasinoAddress        = "192.168.1.10"    
}

object PlayerGUI extends SimpleGUIApplication with Logs {
  def top = new MainFrame {
    title = "LoginPage"

    RemoteActor.classLoader = getClass().getClassLoader()

    val casinoPort = 14500
    val casinoServiceName = 'jackBlack_Casino
    val casinoAddress = "192.168.1.10"
    val virtualCasino = RemoteActor.select(Node(casinoAddress, casinoPort ), casinoServiceName)  
    
    val hostClientPort = 14501
    val hostClientServiceName = 'personPlayer
    val hostClientLocalHost = InetAddress.getLocalHost
    val hostClientIpAddress = hostClientLocalHost.getHostAddress
    var hostClient: ClientPlayer = null
      
    val lUserName = new Label { text = "Username:" }
    var tUserName = new TextField(10);
    val lPassword = new Label { text = "Password:" }
    val tPassword = new PasswordField(10);
    val bSignin = new Button { text = "SignIn" }
    val lNewPlayer = new Label { text = "New to Virtual Casino " }
    val acc = new Button { text = "New Player" }
    val Casino = new Label { text = "VirtualCasino" }
    val casImg = new Label {
        icon = new ImageIcon("Images/Login_BjImage.jpg")
    }
    val loginPanel = new BoxPanel(Orientation.Vertical) {
      contents += Casino
      contents += casImg
    }
    
    val PlayerLoginPanel = new GridPanel(10, 10) {
      hGap = 5
      vGap = 5
      contents += acc
      contents += lUserName
      contents += tUserName
      contents += lPassword
      contents += tPassword
      contents += bSignin
    }
    
    val Fname = new Label { text = "First Name :" }
    val Lname = new Label { text = "Last Name :" }
    val Uname = new Label { text = "Username : " }
    val email = new Label { text = "Email : " }
    val Address = new Label { text = "Address :" }
    val City = new Label { text = "City : " }
    val State = new Label { text = "State :" }
    val Country = new Label { text = "Country :" }
    val Ph = new Label { text = "Phone No : " }
    val Ftxt = new TextField(15); ;
    val Ltxt = new TextField(15);
    val Utxt = new TextField(15);
    val etxt = new TextField(15);
    val addr = new TextField(15);
    val acity = new TextField(15);
    val St = new ComboBox(List("AL", "AR", "AZ", "CA", "CT", "DE", "FL", "GA", "ID", "MI", "NY", "NJ"))
    val Coun = new TextField(15);
    val pno = new TextField(15);
    val save = new Button { text = "Save" }
    val cancel = new Button { text = "Cancel" }
    
    var Playername = new Label { text = "Player Name: " + tUserName.text}
    val SetBankRoll = new Button { text = "SetBankRoll" }
    val TBets = new Button { text = " Tables and Bets" }
    val bets = new Label { text = "Place your bet Here:" }
    val betAmount = new TextField(15);
    	betAmount.editable = false
    val Bet = new Button { text = "Bet" }
    	Bet.enabled = false
    val Help = new Button { text = "Help Me" }
    val exit = new Button { text = "Exit Casino" }
    
    val BetImage = new Label {
      icon = new ImageIcon("Images/PlaceBet.jpg")
    }
    
    val BetFrame = new BoxPanel(Orientation.Vertical) {
      background = java.awt.Color.GREEN
      contents += BetImage
      border = Swing.EmptyBorder(10, 10, 10, 10)
    }

    val SideFrame = new GridPanel(10, 100) {
      hGap = 5
      vGap = 5
      background = java.awt.Color.GREEN
      contents += Playername
      contents += SetBankRoll
      contents += TBets
      contents.append(bets, betAmount)
      contents += Bet
      contents += Help
      contents += exit
      border = Swing.EmptyBorder(10, 0, 10, 10)
    }
    
    val SetLabel = new Label { text = "Set Bank Roll" }
    val card = new Label { text = "Enter your Amount  " }
    val CardAmount = new TextField(15);
    val Tcard = new Label { text = "Select your card type " }
    val Cname = new Label { text = "Name On Card  " }
    val CardName = new TextField(15);
    val Cnum = new Label { text = "Card Number " }
    val CardNum = new TextField(15);
    val Cardsec = new Label { text = "Security Code " }
    val cvv = new TextField(15);
    val Sub = new Button { text = "Submit" }
    val Can = new Button { text = "Cancel" }
    val CardType = new ButtonGroup
    val Visa = new RadioButton("Visa")
    val Master = new RadioButton("Master")
    val Discover = new RadioButton("Discover")
    val CButton = List(Visa, Master, Discover)
    CardType.buttons ++= CButton
    CardType.select(Visa)
    
    val myradios = new BoxPanel(Orientation.Horizontal) {
      contents ++= CButton
    }
    
    val Cexp = new Label { text = "Expiry Date" }
    val CardDate = new ComboBox(1 to 31)
    val CardMon = new ComboBox(List("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
    val Cardyr = new ComboBox(2011 to 2020)
    val CardExpiry = new BoxPanel(Orientation.Horizontal) {
      background = java.awt.Color.GRAY
      contents.append(Cexp, CardDate, CardMon, Cardyr)
      border = Swing.EmptyBorder(10, 10, 0, 10)
    }
    
    val space11 = new Label { text = "" }
    
    val CardFrame = new GridPanel(8, 8) {
      background = java.awt.Color.GRAY
      contents.append(SetLabel, space11)
      contents.append(card, CardAmount)
      contents.append(Tcard, myradios)
      contents.append(Cname, CardName)
      contents.append(Cnum, CardNum)
      contents.append(Cardsec, cvv)
      contents.append(Sub, Can)
      border = Swing.EmptyBorder(10, 10, 10, 10)
    }
    
    val Hit = new Button { text = "Hit" }
    val Stand = new Button { text = "Stand" }
    val DDown = new Button { text = "DoubleDown" }
    val Insurance = new Button { text = "Insurance" }
    val Surr = new Button { text = "Surrender" }
    val Br = new Button { text = "Break" }
    val TableImage = new Label {
      icon = new ImageIcon("Images/BjTable.jpg")
    }
    
    val TableFn = new BoxPanel(Orientation.Horizontal) {
      background = java.awt.Color.GREEN
      contents.append(Hit, Stand, DDown, Insurance, Surr, Br)
      border = Swing.EmptyBorder(10, 0, 10, 0)
    }
    
    val TFrame = new GridPanel(1, 0) {
      hGap = 0
      vGap = 0
      background = java.awt.Color.GREEN
      contents.append(TableImage)
      border = Swing.EmptyBorder(10, 0, 10, 10)
    }
    
    val TbuttonPanel = new GridPanel(1, 0) {
      hGap = 0
      vGap = 0
      background = java.awt.Color.GREEN
      contents.append(TableFn)
      border = Swing.EmptyBorder(10, 0, 10, 10)
    }
    
    val TableFrame = new BoxPanel(Orientation.Vertical) {
      contents.append(TFrame, TbuttonPanel)
    }

    runGUI

    def runGUI {
      contents = new BorderPanel {
        add(loginPanel, BorderPanel.Position.West)
        val space0 = new Label { text = "  " }
        add(space0, BorderPanel.Position.Center)
        add(PlayerLoginPanel, BorderPanel.Position.East)

        border = Swing.EmptyBorder(30, 30, 30, 30)
      }

      listenTo(acc, bSignin) //For the Login Screen
      reactions += {
        case ButtonClicked(`acc`) => runNewAcc
        case ButtonClicked(`bSignin`) => runSignin; 
        	 Playername = new Label { text = "PlayerName: " + tUserName.text }
      }

      def runNewAcc {
        title = "New Player Account"
        contents = new GridPanel(10, 0) {
          contents.append(Fname, Ftxt)
          contents.append(Lname, Ltxt)
          contents.append(Uname, Utxt)
          contents.append(email, etxt)
          contents.append(Address, addr)
          contents.append(City, acity)
          contents.append(State, St)
          contents.append(Country, Coun)
          contents.append(Ph, pno)
          contents.append(save, cancel)
          border = Swing.EmptyBorder(10, 10, 10, 10)
        }
      }

      def runSignin {
        title = "Bj_House"
          println("Player signIn")
          println("Player is: " + tUserName.text)
        contents = new BoxPanel(Orientation.Horizontal) {
          contents += SideFrame
          contents += BetFrame
          border = Swing.EmptyBorder(10, 0, 10, 10)
          
          hostClient= new ClientPlayer(hostClientServiceName, hostClientIpAddress, hostClientPort, tUserName.text, 0, 0) 
          clientStartUp(hostClient)
          hostClient ! SendMsgPlayerName(virtualCasino, tUserName.text)
          println("Player is: " + tUserName.text + " again!")
        }
      }

      listenTo(save, cancel) //For the Login Screen
      reactions += {
        case ButtonClicked(`save`) => runSave
        case ButtonClicked(`cancel`) => runCancel1
      }
      
      def runSave {
          Dialog.showMessage(save,"Player Registered")
      
        PlayerGUI.top.visible = true
      }
      
      def runCancel1 {
        PlayerGUI.top.visible = true
      }

      listenTo(SetBankRoll, TBets, Bet, Help, exit)
      reactions += {
        case ButtonClicked(`SetBankRoll`) => runBankRoll
        case ButtonClicked(`TBets`) => runTBets
        case ButtonClicked(`Bet`) => runBet
        case ButtonClicked(`Help`)=>runHelp
        case ButtonClicked(`exit`)=>runExit
      }
      
      def runBankRoll {
        title = "Bj_SetBankRoll"
        contents = new BoxPanel(Orientation.Horizontal) {
          contents += SideFrame
          contents += CardFrame
          border = Swing.EmptyBorder(10, 20, 10, 20)
        }

      }
      
      def runTBets {
        title = "Tables and Bets"
        val PlaceBet = new Label { text = "Place your bet to start the game" }
        val tableModel = new DefaultTableModel(new Array[Array[AnyRef]](0, 3), // Data
          Array[AnyRef]("TableNo", "Min_Bet", "Max_Bet")) // Column names
        val table = new Table(3, 4) { model = tableModel }
        tableModel.addRow(Array[AnyRef]("TableNo", "Min_Bet", "Max_Bet"))
        tableModel.addRow(Array[AnyRef]("1", "$1", "$10"))
        tableModel.addRow(Array[AnyRef]("2", "$11", "$50"))
        tableModel.addRow(Array[AnyRef]("3", "$51", "$100"))
        tableModel.addRow(Array[AnyRef]("4", "$101", "$200"))
        tableModel.addRow(Array[AnyRef]("5", "$201", "$500"))
        tableModel.addRow(Array[AnyRef]("6", "$501", "$1000"))
        tableModel.addRow(Array[AnyRef]("7", "$1001", "$5000"))
        
        val tablePanel = new BoxPanel(Orientation.Vertical) {
          background = java.awt.Color.GRAY
          contents += PlaceBet
          contents += table
          border = Swing.EmptyBorder(110, 10, 70, 10)
        }
        
        contents = new BoxPanel(Orientation.Horizontal) {
          contents += SideFrame
          contents += tablePanel
          border = Swing.EmptyBorder(10, 10, 10, 10)
        }
      }
      
      def runBet {
        title = "Bj_Table"
        contents = new BoxPanel(Orientation.Horizontal) {
          contents += SideFrame
          contents += TableFrame
          border = Swing.EmptyBorder(10, 10, 0, 10)
          
          hostClient ! SendMsgMakeABet(virtualCasino, betAmount.text.toDouble, hostClient.Pid)
        }
      }
      
      def runHelp{
        Dialog.showMessage(Help,"Refer to http://www.onlineblackjackguru.com/Blackjack-Rules.html")
      }
      
      def runExit{
        close()
      }
      
      listenTo(Sub, Can) //SetBankRoll
      reactions += {
        case ButtonClicked(`Sub`) => runSub; runSetClientBank
        case ButtonClicked(`Can`) => runCancel2
      }
      
      def runSub{
        Dialog.showMessage(Sub,CardAmount.text)
    	betAmount.editable = true
    	Bet.enabled  = true
        debug("SetBankRoll = " + CardAmount.text)
    	runCancel2
      }
      
      def runSetClientBank {
        hostClient ! SendMsgSetBank(virtualCasino, CardAmount.text.toDouble, hostClient.Pid)
      }

      def runCancel2 {
         title = "Bj_House"
         contents = new BoxPanel(Orientation.Horizontal) {
          contents += SideFrame
          contents += BetFrame
          border = Swing.EmptyBorder(10, 10, 10, 10)
        }
      }
      
      def clientStartUp(client: ClientPlayer) {
        println("Client service " +   ClientPlayer.hostClientServiceName + "  Started @ " + 
        							  ClientPlayer.hostClientIpAddress + " on Port:" +  
        							  ClientPlayer.hostClientPort)
        client.start()
        client ! PlayerPid(25)
      }
    }//End runGUI
  }
}